package org.aceor.mddal.group.util;

import com.google.common.collect.LinkedListMultimap;
import com.google.common.collect.Multimap;
import org.aceor.mddal.group.DataSourceWrapper;
import org.aceor.mddal.group.selector.DBSelector;
import org.aceor.mddal.group.selector.EquityDBSelector;
import org.aceor.mddal.group.selector.OneDBSelector;
import org.aceor.mddal.group.selector.PriorityDBGroupSelector;

import java.util.Collections;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;

/**
 * Created by lxue on 16/4/7.
 */
public class RuntimeSelectorHolder {

    private DBSelector rDBSelector;
    private DBSelector wDBSelector;

    private volatile boolean inited = false;

    public void init(Map<String, DataSourceWrapper> dataSourceWrapperMap) {
        if (null == dataSourceWrapperMap || dataSourceWrapperMap.isEmpty()) {
            throw new IllegalArgumentException("dataSourceWrapperMap 不能为空");
        }
        if (dataSourceWrapperMap.size() == 1) {
            //过滤单数据源
            rDBSelector = wDBSelector = new OneDBSelector(dataSourceWrapperMap.values().iterator().next());
        } else {
            Multimap<Integer, DataSourceWrapper> rPriorityMultiMap = LinkedListMultimap.create();
            Multimap<Integer, DataSourceWrapper> wPriorityMultiMap = LinkedListMultimap.create();
            for (DataSourceWrapper dataSourceWrapper : dataSourceWrapperMap.values()) {
                rPriorityMultiMap.put(dataSourceWrapper.getWeight().p, dataSourceWrapper);
                wPriorityMultiMap.put(dataSourceWrapper.getWeight().q, dataSourceWrapper);
            }
            rDBSelector = createDBSelector(rPriorityMultiMap, true);
            wDBSelector = createDBSelector(wPriorityMultiMap, false);
        }
        rDBSelector.setReadable(true);
        wDBSelector.setReadable(false);
        inited = true;
    }

    private DBSelector createDBSelector(Multimap<Integer, DataSourceWrapper> priorityMultiMap, boolean isRead) {
        if (priorityMultiMap.keySet().size() == 1) {
            //priorityMultiMap.keySet().size() == 1时,如果priorityMultiMap.values().size()==1,那么就代表只有一个数据源,这种情况在init中已经过滤掉了
            return GroupDsUtil.createEquityDbManager(priorityMultiMap.values(), isRead);
        } else {
            List<Integer> priorityKeys = new LinkedList<Integer>();
            priorityKeys.addAll(priorityMultiMap.keySet());
            Collections.sort(priorityKeys); // 优先级从小到大排序
            int len = priorityKeys.size();
            EquityDBSelector[] priorityGroups = new EquityDBSelector[len];
            for (int i = 0; i < len; i++) { // 最大的优先级放到最前面
                // PriorityDbGroupSelector依赖EquityDbManager抛出的NoMoreDataSourceException来实现，
                // 所以这里即使只有一个ds也只能仍然用EquityDbManager
                priorityGroups[i] = GroupDsUtil.createEquityDbManager(
                        priorityMultiMap.get(
                                priorityKeys.get(len - 1 - i)), isRead);
            }
            return new PriorityDBGroupSelector(priorityGroups);
        }
    }

    public DBSelector getDBSelector(boolean isRead) {
        if (!inited) {
            throw new RuntimeException("RuntimeSelectorHolder has not been inited");
        }
        return isRead ? rDBSelector : wDBSelector;
    }
}
